#ifndef CGRAVITATIONAL_ACRETION_H
#define CGRAVITATIONAL_ACRETION_H

#include <vector>
#include <list>
#include <iostream>
#include <time.h>
#include <stdio.h>
#include <limits>
using namespace std;

#define  GravityConstant 6.66e-11

#include "CImg.h"
using namespace cimg_library;

template <typename _SNO> class CGravitationalAcretion {
public:
	typedef typename _SNO::particle_t				particle_t;
	typedef typename particle_t::value_pattern_t	value_pattern_t;
	typedef typename particle_t::label_t			label_t;
	typedef typename particle_t::gravity_t			gravity_t;
	typedef typename particle_t::velocity_t			velocity_t;
	typedef typename particle_t::pattern_t			pattern_t;
	typedef list<particle_t>						container_t;


public:

	CGravitationalAcretion (container_t &_particles, double _betha, double _k, int _t){
		print_to_image(_particles,"google.bmp");
		for (int  x = 2; x < _t; x++){
			long double gconst = GravityConstant + (pow(1,_betha) / x) * _betha;
			cout << x << " Gravedad : " << gconst << endl;

			container_t::iterator it = _particles.begin ();
			for (; it != _particles.end(); it++){
				container_t::iterator sit = _particles.begin ();
				for (; sit != _particles.end(); sit++){
					if (sit->_id == it->_id)  continue;
					long double dist = it->mean().distancia_euclideana(sit->mean()) * it->mean().distancia_euclideana(sit->mean());
					dist = (dist == 0)?_k: dist;
					it->_distance = gconst * sit->size() / (2 * dist);
					it->_position += (**sit - **it) * (it->_distance) / (**sit - **it).norma();
				}
			}
			container_t::iterator sit = _particles.begin ();
			for (; sit != _particles.end(); sit++){
				cout << sit->_position << endl;
			}
			cout << "----------------------------------" << endl << endl;
		}
		container_t::iterator sit = _particles.begin ();
		for (; sit != _particles.end(); sit++){
			sit->_position.round();
			cout << sit->_position << endl;
		}
	}				


	void print_to_image (container_t &_particles, string img){
		CImg<unsigned char> image(img.c_str());
		for (int i = 0; i < image.width(); i++)
			for (int k = 0; k < image.height(); k++)
				for (int f = 0; f < 3; f++)
					image(i,k,f) = 0;

		container_t::iterator sit = _particles.begin ();
		for (; sit != _particles.end(); sit++){
			sit->_position.round();
			if (sit->_mean._label == "Iris-virginica"){
				image(sit->_position[0],sit->_position[1],0) = 250;
				image(sit->_position[0],sit->_position[1],1) = 0;
				image(sit->_position[0],sit->_position[1],2) = 0;
			}
			if (sit->_mean._label == "Iris-versicolor"){
				image(sit->_position[0],sit->_position[1],0) = 0;
				image(sit->_position[0],sit->_position[1],1) = 250;
				image(sit->_position[0],sit->_position[1],2) = 0;
			}
			if (sit->_mean._label == "Iris-setosa"){
				image(sit->_position[0],sit->_position[1],0) = 0;
				image(sit->_position[0],sit->_position[1],1) = 0;
				image(sit->_position[0],sit->_position[1],2) = 250;
			}
		}
		image.display();
		image.save("result.bmp");
	}


	~CGravitationalAcretion (void){
	}

};

#endif